package com.punch.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.punch.common.dto.system.area.AreaDTO;
import com.punch.common.exception.BusinessException;
import com.punch.common.vo.system.area.AppAreaVO;
import com.punch.common.vo.system.area.TreeAreaVO;
import com.punch.system.exception.SysExceptionEnum;
import com.punch.system.mapper.SysNationAreaMapper;
import com.punch.system.model.SysNationArea;
import com.punch.system.service.NationAreaService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * <p>
 * 全国地区表 服务实现类
 * </p>
 *
 * @author wjj
 * @since 2020-12-04
 */
@Service
public class NationAreaServiceImpl extends ServiceImpl<SysNationAreaMapper, SysNationArea> implements NationAreaService {

    /**
     * 地区树形-pc端,地区管理
     *
     * @param parentId 地区父id,默认为0
     * @return List<TreeAreaVO>
     * @author wujj
     * @since 2020/6/4 19:16
     */
    @Override
    public List<TreeAreaVO> treeArea(Integer parentId) {
        return getBaseMapper().selectListByPid(parentId);
    }

    /**
     * 地区树形（根据状态查询）
     *
     * @param status   状态 0-停用 1-启用
     * @param parentId 父节点id
     * @param type     类型
     * @return List<TreeAreaVO>
     * @author wujj
     * @since 2020/6/4 19:16
     */
    @Override
    public List<TreeAreaVO> treeAreaStatus(Integer status, Integer parentId, Integer type) {
        //查看是否有子集
        SysNationArea sysArea = getById(parentId);
        Optional.ofNullable(sysArea).orElseThrow(() -> new BusinessException(SysExceptionEnum.AREA_NOT_EXIST));
        List<TreeAreaVO> retList;
        if (type == 0) {
            //说明没有子集返回自身
            retList = new ArrayList<>();
            TreeAreaVO treeAreaVO = new TreeAreaVO();
            BeanUtils.copyProperties(sysArea, treeAreaVO);
            treeAreaVO.setAreaId(sysArea.getId());
            retList.add(treeAreaVO);
        } else {
            retList = getBaseMapper().treeAreaStatus(status, parentId);
        }
        return retList;
    }

    /**
     * 新增地区
     *
     * @param areaDTO 地区新增表单
     * @return areaId
     * @author wujj
     * @since 2020/6/4 19:33
     */
    @Override
    public Integer saveArea(AreaDTO areaDTO) {
        SysNationArea area = new SysNationArea();
        BeanUtils.copyProperties(areaDTO, area);
        //数据重复校验
        Integer parentId = areaDTO.getParentId();
        areaRepeatCheck(areaDTO.getShortName(), parentId == null ? 0 : areaDTO.getParentId(), 0);
        //判断是否有父级
        SysNationArea parentArea = null;
        if (null != parentId && 0 != parentId) {
            parentArea = getById(parentId);
            if (parentArea == null) {
                throw new BusinessException(SysExceptionEnum.PARENT_DATA_DOES_NOT_EXIST);
            }
            area.setParentId(parentId);
            area.setParentIds(parentArea.getParentIds() + "," + parentArea.getId());
            area.setLevel(parentArea.getLevel() + 1);
        }
        if (!save(area)) {
            throw new BusinessException(SysExceptionEnum.DATA_INSERT_EXCEPTION);
        }
        //数据保存成功,父级"直接子集数量"加1
        if (null != parentArea) {
            Integer number = parentArea.getChildNumber() + 1;
            parentArea.setChildNumber(number);
            if (!updateById(parentArea)) {
                throw new BusinessException(SysExceptionEnum.UPDATE_PARENT_DATA_EXCEPTION);
            }
        }
        return area.getId();
    }

    /**
     * 修改地区
     *
     * @param areaDTO 地区更新表单
     * @return areaId
     * @author wujj
     * @since 2020/6/4 19:46
     */
    @Override
    public Integer updateArea(AreaDTO areaDTO) {
        //校验数据是否存在
        SysNationArea sysAreaEx = getById(areaDTO.getAreaId());
        Optional.ofNullable(sysAreaEx).orElseThrow(() -> new BusinessException(SysExceptionEnum.AREA_NOT_EXIST));
        SysNationArea area = new SysNationArea();
        BeanUtils.copyProperties(areaDTO, area);
        area.setId(areaDTO.getAreaId());
        //数据重复校验
        areaRepeatCheck(areaDTO.getShortName(), areaDTO.getParentId(), sysAreaEx.getId());
        if (!sysAreaEx.getShortName().equals(areaDTO.getShortName()) && 0 != areaDTO.getParentId()) {
            SysNationArea parentArea = getById(area.getParentId());
            if (null == parentArea) {
                throw new BusinessException(SysExceptionEnum.PARENT_DATA_DOES_NOT_EXIST);
            }
        }
        if (!updateById(area)) {
            throw new BusinessException(SysExceptionEnum.DATA_UPDATE_EXCEPTION);
        }
        return areaDTO.getAreaId();
    }

    /**
     * 删除地区
     *
     * @param areaId 地区id
     * @return areaId
     * @author wujj
     * @since 2020/6/4 19:54
     */
    @Override
    public Integer deleteArea(Integer areaId) {
        //校验数据是否存在
        SysNationArea sysAreaEx = getById(areaId);
        Optional.ofNullable(sysAreaEx).orElseThrow(() -> new BusinessException(SysExceptionEnum.AREA_NOT_EXIST));
        //获取指定地区下全部地区数据（含本身）
        UpdateWrapper<SysNationArea> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda()
                .apply("FIND_IN_SET({0},parent_ids)", areaId)
                .or().eq(SysNationArea::getId, areaId);
        //删除自身及所有下级数据
        if (!remove(updateWrapper)) {
            throw new BusinessException(SysExceptionEnum.DATA_DELETION_EXCEPTION);
        }
        //如有父级，则父级“直接子集数量”减1
        if (0 != sysAreaEx.getParentId()) {
            SysNationArea parentArea = getById(sysAreaEx.getParentId());
            if (null == parentArea) {
                throw new BusinessException(SysExceptionEnum.PARENT_DATA_DOES_NOT_EXIST);
            }
            parentArea.setChildNumber(parentArea.getChildNumber() - 1);
            if (!updateById(parentArea)) {
                throw new BusinessException(SysExceptionEnum.UPDATE_PARENT_DATA_EXCEPTION);
            }
        }

        return areaId;
    }

    /**
     * 地区信息
     *
     * @param areaId 地区id
     * @return TreeAreaVO
     * @author wujj
     * @since 2020/6/4 19:16
     */
    @Override
    public TreeAreaVO getFeignArea(Integer areaId) {
        SysNationArea sysArea = getById(areaId);
        TreeAreaVO treeAreaVO = new TreeAreaVO();
        BeanUtils.copyProperties(sysArea, treeAreaVO);
        return treeAreaVO;
    }

    /**
     * 查找该地区id下的子id
     *
     * @param parentId 地区父id
     * @return List<Long>
     * @author wujj
     * @since 2020/6/4 19:16
     */
    @Override
    public List<Integer> listFeignChildId(Integer parentId) {
        QueryWrapper<SysNationArea> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().apply("FIND_IN_SET({0},parent_ids)", parentId);
        List<SysNationArea> list = list(queryWrapper);
        List<Integer> retList = new ArrayList<>();
        list.forEach(sysArea -> retList.add(sysArea.getId()));
        return retList;
    }

    /**
     * 地区启用/停用
     *
     * @param areaId
     */
    @Override
    public void enableArea(Integer areaId) {
        SysNationArea sysAreaEX = getById(areaId);
        Optional.ofNullable(sysAreaEX).orElseThrow(() -> new BusinessException(SysExceptionEnum.AREA_NOT_EXIST));
        SysNationArea updateArea = new SysNationArea();
        //启用变成停用
        Integer status = 0;
        if (sysAreaEX.getStatus() == 1) {
            updateArea.setStatus(status);
        }
        //停用变成启用
        if (sysAreaEX.getStatus() == 0) {
            status = 1;
            updateArea.setStatus(status);
        }
        updateArea.setId(areaId);
        updateById(updateArea);

        //父级停用子级也全部停用
        //获取指定地区下全部地区数据（含本身）
        QueryWrapper<SysNationArea> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().apply("FIND_IN_SET({0},parent_ids)", areaId);
        List<SysNationArea> childList = list(queryWrapper);
        if (CollUtil.isNotEmpty(childList)) {
            List<SysNationArea> updateList = new ArrayList<>();
            childList.forEach(sysArea -> {
                sysArea.setStatus(updateArea.getStatus());
                updateList.add(sysArea);
            });
            updateBatchById(updateList);
        }
    }

    /**
     * app端地区
     *
     * @param parentId 地区父id,默认为0
     * @return List<TreeAreaVO>
     * @author wujj
     * @since 2020/6/4 19:16
     */
    @Override
    public List<AppAreaVO> appArea(Integer parentId) {
        if (parentId == 0L) {
            parentId = 999999999;//999999999为中国的id
        }
        return getBaseMapper().selectAppListByPid(parentId);
    }

    /**
     * 获取父ids
     *
     * @param areaId 地区id
     * @return string
     */
    @Override
    public String getParentIds(Integer areaId) {
        return getById(areaId).getParentIds();
    }

    /**
     * 数据重复校验
     *
     * @param shortName 地区名称
     * @param areaId    地区id，新增为0
     * @param parentId  父id
     * @author wujj
     * @since 2020/6/6 11:25
     */
    private void areaRepeatCheck(String shortName, Integer parentId, Integer areaId) {
        //校验同级地区名是否重复
        QueryWrapper<SysNationArea> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(SysNationArea::getParentId, parentId)
                .eq(SysNationArea::getShortName, shortName);
        if (areaId != 0) {
            queryWrapper.lambda().notIn(SysNationArea::getId, areaId);
        }
        if (count(queryWrapper) > 0) {
            throw new BusinessException(SysExceptionEnum.SIBLING_DATA_NAMES_ARE_NOT_REPEATABLE);
        }
    }
}
